import uuid
from PySide6.QtWidgets import (QGraphicsItem, QGraphicsRectItem,
                               QGraphicsTextItem, QMenu, QWidget, QVBoxLayout,
                               QLabel, QLineEdit, QDoubleSpinBox, QComboBox,
                               QGraphicsTextItem, QGraphicsProxyWidget, QLineEdit)
from PySide6.QtCore import Qt, QRectF, QPointF, Signal
from PySide6.QtGui import QBrush, QPen, QColor, QAction, QFocusEvent


class PortItem(QGraphicsRectItem):
    def __init__(self, portName, isInput, parentNode):
        super().__init__(-8, -8, 16, 16, parentNode)  # 增大点击区域
        self.portName = portName
        self.isInput = isInput
        self.parentNode = parentNode
        self.connections = []

        # 根据端口类型设置颜色
        if self.isInput:
            self.normalColor = QColor(100, 150, 255)  # 蓝色输入端口
            self.hoverColor = QColor(120, 170, 255)
        else:
            self.normalColor = QColor(100, 255, 150)  # 绿色输出端口
            self.hoverColor = QColor(120, 255, 170)

        self.setBrush(QBrush(self.normalColor))
        self.setPen(QPen(Qt.black, 1))
        self.setFlag(QGraphicsItem.ItemIsSelectable)
        self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges)

        # 设置悬停效果
        self.setAcceptHoverEvents(True)

    def hoverEnterEvent(self, event):
        """鼠标悬停时改变颜色"""
        self.setBrush(QBrush(self.hoverColor))
        super().hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        """鼠标离开时恢复颜色"""
        self.setBrush(QBrush(self.normalColor))
        super().hoverLeaveEvent(event)

    def canAcceptConnection(self):
        """检查端口是否可以接受新连接"""
        # 输入端口只能有一个连接
        if self.isInput and len(self.connections) > 0:
            return False
        return True

    def addConnection(self, connection):
        """添加连接"""
        if self.canAcceptConnection():
            self.connections.append(connection)
            return True
        return False

    def removeConnection(self, connection):
        """移除连接"""
        if connection in self.connections:
            self.connections.remove(connection)

    def updateConnections(self):
        """更新所有连接的路径"""
        for connection in self.connections:
            if hasattr(connection, 'updatePath'):
                connection.updatePath()

    def updateTheme(self, theme):
        """根据主题更新端口颜色 - 现在固定颜色，不受主题影响"""
        # 输入端口始终为蓝色，输出端口始终为绿色，不受主题影响
        if self.isInput:  # 这里 self.isInput 是正确的，因为这是在 PortItem 类中
            self.normalColor = QColor(100, 150, 255)  # 蓝色输入端口
            self.hoverColor = QColor(120, 170, 255)
        else:
            self.normalColor = QColor(100, 255, 150)  # 绿色输出端口
            self.hoverColor = QColor(120, 255, 170)

        self.setBrush(QBrush(self.normalColor))

    def getConnectionData(self):
        """获取连接的序列化数据"""
        connectionsData = []
        for connection in self.connections:
            if connection.startPort == self:
                otherPort = connection.endPort
            else:
                otherPort = connection.startPort

            connectionsData.append({
                'nodeId': otherPort.parentNode.nodeId,
                'portName': otherPort.portName,
                'isInput': otherPort.isInput
            })
        return connectionsData


class AudioNode(QGraphicsRectItem):
    nameChanged = Signal(str)  # 新名称

    def __init__(self, nodeData, position=None, nodeId=None):
        super().__init__(0, 0, 120, 80)
        self.nodeData = nodeData
        self.nodeType = nodeData.get('type')
        # 使用UUID作为唯一标识符
        self.nodeId = nodeId if nodeId else str(uuid.uuid4())
        self.inputPorts = {}
        self.outputPorts = {}
        self.parameterValues = {}
        self.customName = None  # 自定义名称
        self.nameEditWidget = None  # 名称编辑控件
        self.nameProxy = None  # 代理窗口

        # 初始化参数值为默认值
        parameters = nodeData.get('parameters', {})
        for paramName, paramConfig in parameters.items():
            self.parameterValues[paramName] = paramConfig.get('default', 0.0)

        # 设置节点样式
        self.setBrush(QBrush(QColor(60, 60, 60)))
        self.setPen(QPen(QColor(200, 200, 200), 2))
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges)

        if position:
            self.setPos(position)

        self.initPorts()
        self.initTitle()

    def initTitle(self):
        """初始化节点标题"""
        self.title = QGraphicsTextItem(self.getDisplayName(), self)
        self.title.setDefaultTextColor(Qt.white)
        self.title.setPos(5, 5)
        # 设置标题为不可编辑，我们将使用单独的编辑控件
        self.title.setTextInteractionFlags(Qt.NoTextInteraction)

    def getDisplayName(self):
        """获取显示名称"""
        return self.customName if self.customName else self.nodeData.get('name', 'Unknown')

    def getCanvas(self):
        """获取画布引用"""
        if self.scene() and self.scene().views():
            return self.scene().views()[0]
        return None

    def setNodeName(self, new_name):
        """设置节点名称"""
        if new_name and new_name.strip():
            self.customName = new_name.strip()
            self.title.setPlainText(self.customName)

            # 通知画布更新设置面板
            canvas = self.getCanvas()
            if canvas and hasattr(canvas, 'updateNodeNameInSettings'):
                canvas.updateNodeNameInSettings(self.nodeId, self.customName)

    def mouseDoubleClickEvent(self, event):
        """双击事件 - 启动重命名"""
        # 检查是否点击在标题区域
        title_rect = self.title.boundingRect()
        title_rect.translate(self.title.pos())
        if title_rect.contains(event.pos()):
            self.startRename()
            event.accept()
        else:
            super().mouseDoubleClickEvent(event)

    def startRename(self):
        """启动重命名编辑"""
        # 如果已经在编辑中，先完成之前的编辑
        if self.nameEditWidget:
            self.finishRename()

        # 创建行编辑控件
        self.nameEditWidget = QLineEdit()
        self.nameEditWidget.setText(self.getDisplayName())

        # 创建代理窗口
        self.nameProxy = QGraphicsProxyWidget(self)
        self.nameProxy.setWidget(self.nameEditWidget)
        self.nameProxy.setPos(5, 5)
        self.nameProxy.setMaximumWidth(110)

        # 连接信号
        self.nameEditWidget.returnPressed.connect(self.finishRename)
        self.nameEditWidget.editingFinished.connect(self.finishRename)

        # 隐藏原始标题
        self.title.hide()

        # 设置焦点并选中所有文本
        self.nameEditWidget.setFocus()
        self.nameEditWidget.selectAll()

    def finishRename(self):
        """完成重命名"""
        if not self.nameEditWidget:
            return

        new_name = self.nameEditWidget.text()
        self.setNodeName(new_name)

        # 清理编辑控件
        if self.nameProxy:
            self.nameProxy.setWidget(None)
            self.nameProxy.deleteLater()
            self.nameProxy = None

        if self.nameEditWidget:
            self.nameEditWidget.deleteLater()
            self.nameEditWidget = None

        # 显示原始标题
        self.title.show()

        # 标记项目有未保存的更改 - 通过画布
        canvas = self.getCanvas()
        if canvas and hasattr(canvas, 'markUnsavedChanges'):
            canvas.markUnsavedChanges()

    def initPorts(self):
        """初始化输入输出端口"""
        # 创建输入端口
        inputs = self.nodeData.get('inputs', [])
        for i, inputName in enumerate(inputs):
            port = PortItem(inputName, True, self)
            port.setPos(0, 20 + i * 20)
            self.inputPorts[inputName] = port

        # 创建输出端口
        outputs = self.nodeData.get('outputs', [])
        for i, outputName in enumerate(outputs):
            port = PortItem(outputName, False, self)
            port.setPos(self.rect().width(), 20 + i * 20)
            self.outputPorts[outputName] = port

    def itemChange(self, change, value):
        """处理项目变化事件"""
        if change == QGraphicsItem.GraphicsItemChange.ItemPositionHasChanged:
            # 节点位置改变时更新所有连接的路径
            self.updateAllConnections()

        return super().itemChange(change, value)

    def updateAllConnections(self):
        """更新所有连接到该节点的连接"""
        # 更新所有输入端口的连接
        for port in self.inputPorts.values():
            port.updateConnections()

        # 更新所有输出端口的连接
        for port in self.outputPorts.values():
            port.updateConnections()

    def getInputPort(self, portName):
        return self.inputPorts.get(portName)

    def getOutputPort(self, portName):
        return self.outputPorts.get(portName)

    def setParameterValue(self, paramName, value):
        """设置参数值"""
        self.parameterValues[paramName] = value

    def getParameterValue(self, paramName):
        """获取参数值"""
        return self.parameterValues.get(paramName)

    def updateTheme(self, theme):
        """根据主题更新节点颜色"""
        if theme == "light":
            # 白天主题：浅色背景，深色边框
            self.setBrush(QBrush(QColor(240, 240, 240)))
            self.setPen(QPen(QColor(80, 80, 80), 2))
            self.title.setDefaultTextColor(QColor(0, 0, 0))
        else:  # dark theme
            # 黑夜主题：深色背景，浅色边框
            self.setBrush(QBrush(QColor(60, 60, 60)))
            self.setPen(QPen(QColor(200, 200, 200), 2))
            self.title.setDefaultTextColor(QColor(255, 255, 255))

        # 更新端口颜色
        for port in list(self.inputPorts.values()) + list(self.outputPorts.values()):
            if hasattr(port, 'updateTheme'):
                port.updateTheme(theme)

    def getSerializationData(self):
        """获取节点序列化数据"""
        return {
            'nodeId': self.nodeId,
            'nodeType': self.nodeType,
            'position': {
                'x': self.pos().x(),
                'y': self.pos().y()
            },
            'parameters': self.parameterValues.copy()
        }

    def contextMenuEvent(self, event):
        """右键菜单"""
        menu = QMenu()

        renameAction = QAction("重命名", menu)
        renameAction.triggered.connect(self.startRename)

        copyAction = QAction("复制", menu)
        copyAction.triggered.connect(lambda: self.getCanvas().copyNode(self))

        cutAction = QAction("剪切", menu)
        cutAction.triggered.connect(lambda: self.getCanvas().cutNode(self))

        deleteAction = QAction("删除", menu)
        deleteAction.triggered.connect(lambda: self.getCanvas().deleteNode(self))

        settingsAction = QAction("设置", menu)
        settingsAction.triggered.connect(lambda: self.getCanvas().showNodeSettings(self))

        menu.addAction(renameAction)
        menu.addSeparator()
        menu.addAction(copyAction)
        menu.addAction(cutAction)
        menu.addAction(deleteAction)
        menu.addAction(settingsAction)

        menu.exec_(event.screenPos())

    def getSerializationData(self):
        """获取节点序列化数据"""
        return {
            'nodeId': self.nodeId,
            'nodeType': self.nodeType,
            'position': {
                'x': self.pos().x(),
                'y': self.pos().y()
            },
            'parameters': self.parameterValues.copy(),
            'customName': self.customName  # 保存自定义名称
        }